package com.ziyueyuwen.xiniao.controller.wx;

import com.alibaba.fastjson.JSONObject;
import com.suyeer.basic.util.HttpResUtil;
import com.suyeer.basic.util.JsonUtil;
import com.suyeer.basic.util.LogUtil;
import com.suyeer.cache.RedisUtil;
import com.suyeer.fastwechat.util.FwUtil;
import com.ziyueyuwen.xiniao.base.BaseUtil;
import com.ziyueyuwen.xiniao.base.HttpResContent;
import com.ziyueyuwen.xiniao.bean.ZyUser;
import com.ziyueyuwen.xiniao.bean.wx.TbWxUserInfo;
import com.ziyueyuwen.xiniao.dao.TbWxUserInfoMapper;
import com.ziyueyuwen.xiniao.service.ThirdPartService;
import com.ziyueyuwen.xiniao.service.UserService;
import com.ziyueyuwen.xiniao.util.ConstUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.ziyueyuwen.xiniao.base.BaseUtil.*;
import static com.ziyueyuwen.xiniao.util.ConstUtil.*;

/**
 * @author jun 2018/12/4
 */
@Controller
@RequestMapping("/wx")
public class WxController {

    @Autowired
    private UserService userService;

    @Autowired
    private ThirdPartService thirdPartService;

    @Autowired
    private TbWxUserInfoMapper tbWxUserInfoMapper;

    /**
     * 聊天测试页面
     *
     * @return String
     */
    @RequestMapping(value = "/chat", method = RequestMethod.GET)
    public String chat() {
        HttpResContent<Boolean> hrc = new HttpResContent<>("聊天页面");
        hrc.setWxRedirect("/wx/chat");
        try {
            checkWxVisitor(hrc);
            hrc.getRequest().setAttribute("wxUserInfoObj", JsonUtil.toJSONObject(hrc.getWxUserInfo()));
            hrc.getRequest().setAttribute("wxConfigObj", FwUtil.getJsSdkConfig(hrc.getRequest()));
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        }
        return hrc.getWxRedirect();
    }

    /**
     * 微信授权跳转控制器, 自动收集新用户的微信数据
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @return String
     */
    @RequestMapping(method = RequestMethod.GET)
    public String index(@RequestParam(value = PARAM_ORIGINAL_URL, required = false) String originalUrl,
                        HttpServletRequest request, HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("微信授权");
        try {
            originalUrl = StringUtils.defaultIfBlank(originalUrl, "https://wx.ziyueyuwen.com/courseList");
            hrc.setWxRedirect(REDIRECT + originalUrl);
            checkWxVisitor(hrc);
            // 系统账号直接登录
            ZyUser zyUser = thirdPartService.getUserMessage(hrc.getWxUserInfo().getWxUserId());
            if (zyUser != null) {
                zyUser.setUserPassword(null);
                hrc.setUserSession(zyUser);
            }
            saveSuccessMsgAndData(hrc, true);
        } catch (IllegalAccessException e) {
            LogUtil.info(e.getMessage());
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        }
        return hrc.getWxRedirect();
    }

    /**
     * 检查微信用户访问; 老用户会通过静默授权获取openid, 然后根据openid查找微信用户信息的方式登录;
     * 新用户会通过高级授权先保存微信用户信息, 然后设置登录;
     *
     * @param hrc HttpResContent<Boolean>
     * @throws IllegalAccessException Exception
     */
    private void checkWxVisitor(HttpResContent hrc) throws IllegalAccessException {
        if (!hrc.isWxLogin()) {
            hrc.saveOriginalQueryURI();
            hrc.setWxRedirect(ConstUtil.REDIRECT + WX_URL_SILENT_AUTH);
            throw new IllegalAccessException("当前地址需要在微信端访问, 正在跳转至微信静默授权获取信息...");
        }
    }

    @RequestMapping(value = "/check_login.do", method = RequestMethod.POST)
    public void checkLogin(HttpServletRequest request, HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("检查登录状态");
        try {
            JSONObject retObj = new JSONObject();
            retObj.put("isWxLogin", hrc.isWxLogin());
            retObj.put("isUserLogin", hrc.isLogin());
            if (hrc.isWxLogin()) {
                retObj.put("wxUserId", hrc.getWxUserInfo().getWxUserId());
            }
            if (hrc.isLogin()) {
                retObj.put("sysUserName", hrc.getUserInfo().getUserName());
            }
            hrc.fillData(HttpStatus.SC_OK, "check_login", retObj);
        } catch (Exception e) {
            BaseUtil.saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    @RequestMapping(value = "/check_bind.do", method = RequestMethod.POST)
    public void checkBind(@RequestParam(PARAM_PHONE_NUM) String phoneNum,
                          HttpServletRequest request, HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("检查绑定");
        try {
            // check.
            checkParam(PARAM_PHONE_NUM, phoneNum);
            // do.
            JSONObject retObj = new JSONObject();
            retObj.put("wxUserInfo", hrc.getWxUserInfo());
            retObj.put("wxHaveBindOtherUser", false);
            retObj.put("wrongPhoneNum", true);
            retObj.put("phoneNumHaveBindOtherWx", false);
            ZyUser zyUser = thirdPartService.getUserMessage(hrc.getWxUserInfo().getWxUserId());
            if (zyUser != null) {
                // 当前微信绑定了手机号
                retObj.put("wxHaveBindOtherUser", true);
                retObj.put("userName", zyUser.getUserName());
                retObj.put("userAccount", zyUser.getUserAccount());
            }
            ZyUser zyUser1 = userService.getByAccount(phoneNum);
            if (zyUser1 != null) {
                // 输入的手机号存在
                retObj.put("wrongPhoneNum", false);
                retObj.put("phoneNumUserName", zyUser1.getUserName());
            }
            TbWxUserInfo tbWxUserInfo = thirdPartService.getWxMessage(phoneNum);
            if (tbWxUserInfo != null) {
                // 当前手机号绑定了其他微信
                retObj.put("phoneNumHaveBindOtherWx", true);
                retObj.put("wxUserNickname", tbWxUserInfo.getNickname());
                retObj.put("wxHeadImgUrl", tbWxUserInfo.getHeadImgUrl());
            }
            saveSuccessMsgAndData(hrc, retObj);
        } catch (Exception e) {
            BaseUtil.saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    @RequestMapping(value = "/get_bind_info.do", method = RequestMethod.POST)
    public void getBindInfo(HttpServletRequest request, HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取绑定信息");
        try {
            JSONObject retObj = new JSONObject();
            TbWxUserInfo tbWxUserInfo = hrc.getWxUserInfo();
            ZyUser zyUser = thirdPartService.getUserMessage(tbWxUserInfo.getWxUserId());
            if (zyUser == null) {
                throw new Exception("您尚未绑定学习账号");
            }
            retObj.put("userName", zyUser.getUserName());
            retObj.put("userAccount", zyUser.getUserAccount());
            retObj.put("wxUserNickname", tbWxUserInfo.getNickname());
            retObj.put("wxHeadImgUrl", tbWxUserInfo.getHeadImgUrl());
            saveSuccessMsgAndData(hrc, retObj);
        } catch (Exception e) {
            BaseUtil.saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    @RequestMapping(value = "/do_bind.do", method = RequestMethod.POST)
    public void doBind(@RequestParam(PARAM_PHONE_NUM) String phoneNum,
                       HttpServletRequest request, HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("绑定账号");
        try {
            // check.
            checkParam(PARAM_PHONE_NUM, phoneNum);
            // do.
            String wxUserId = hrc.getWxUserInfo().getWxUserId();
            thirdPartService.bindWx(phoneNum, wxUserId);
            ZyUser zyUser = userService.getByAccount(phoneNum);
            if (zyUser != null) {
                hrc.setUserSession(zyUser);
                RedisUtil.del(DATABASE_FOR_UPDATE_USER, KEY_UPDATE_USER_INFO + phoneNum);
            }
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            BaseUtil.saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    @RequestMapping(value = "/delete_bind.do", method = RequestMethod.POST)
    public void deleteBind(HttpServletRequest request, HttpServletResponse response) {
        HttpResContent<Boolean> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("解除绑定");
        try {
            if (hrc.isWxLogin()) {
                TbWxUserInfo wxUserInfo = hrc.getWxUserInfo();
                thirdPartService.removeWxBindByWxUserId(wxUserInfo.getWxUserId());
            }
            hrc.setUserSession(null);
            saveSuccessMsgAndData(hrc, true);
        } catch (Exception e) {
            BaseUtil.saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    @RequestMapping(value = "/get_config.do", method = RequestMethod.POST)
    public void getConfig(@RequestParam(PARAM_URL) String url,
                          HttpServletRequest request, HttpServletResponse response) {
        HttpResContent<JSONObject> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取微信JsApi参数配置");
        try {
            // check.
            checkParam(PARAM_URL, url);
            // do.
            JSONObject retObj = FwUtil.getJsSdkConfig(url);
            saveSuccessMsgAndData(hrc, retObj);
        } catch (Exception e) {
            BaseUtil.saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    /**
     * 为了方便在网页端调试微信页面, 这里直接开放个接口, 直接在pc上登录微信
     *
     * @param key String
     */
    @RequestMapping(value = "/wx_test", method = RequestMethod.GET)
    public void wxTest(@RequestParam(PARAM_KEY) String key) throws Exception {
        HttpResContent<Boolean> hrc = new HttpResContent<>("微信登录测试");
        // check.
        checkParam(PARAM_KEY, key);
        // do.
        TbWxUserInfo tbWxUserInfo;
        if (key.startsWith("wx")) {
            tbWxUserInfo = tbWxUserInfoMapper.getByWxUserId(key);
            if (tbWxUserInfo == null) {
                throw new Exception("当前微信号不存在!");
            }
        } else {
            tbWxUserInfo = tbWxUserInfoMapper.getByAccount(key);
            if (tbWxUserInfo == null) {
                throw new Exception("当前手机号未绑定微信!");
            }
        }
        // 系统账号直接登录
        ZyUser zyUser = thirdPartService.getUserMessage(tbWxUserInfo.getWxUserId());
        if (zyUser != null) {
            zyUser.setUserPassword(null);
            hrc.setUserSession(zyUser);
        }
        hrc.setWxUserSession(tbWxUserInfo);
        hrc.printLogAndResponse(true);
    }

    @RequestMapping(value = "/wx_author", method = RequestMethod.GET)
    public String wxAuthor(@RequestParam(PARAM_KEY) String key,
                           @RequestParam(PARAM_URL) String url) throws Exception {
        HttpResContent<Boolean> hrc = new HttpResContent<>("授权其他微信做题");
        // check.
        checkParam(PARAM_KEY, key);
        // do.
        try {
            url = StringUtils.defaultIfBlank(url, "https://wx.ziyueyuwen.com/courseList");
            hrc.setWxRedirect(REDIRECT + url);
            checkWxVisitor(hrc);
            // 系统账号直接登录
            ZyUser zyUser = thirdPartService.getUserMessage(key);
            if (zyUser != null) {
                zyUser.setUserPassword(null);
                hrc.setUserSession(zyUser);
            }
            saveSuccessMsgAndData(hrc, true);
        } catch (IllegalAccessException e) {
            LogUtil.info(e.getMessage());
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        }
        return hrc.getWxRedirect();
    }

}
